home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 4 / The Arsenal Files 4 (Arsenal Computer).ISO / casm / au116-as.exe / UTIL / GFORMAT.CPP < prev    next >
C/C++ Source or Header  |  1994-12-19  |  12KB  |  416 lines

  1. #include "..\au.hpp"
  2. /***************************************************************/
  3.  
  4. #define LAST_BYTE 20600 /* For speed purposed, don't check beyond this point */
  5.  
  6. struct CHECK
  7. {
  8.     int search_pos;
  9.     char *match;
  10.     int start_pos;
  11.     char is_self;
  12.     ARC_TYPE type;
  13.     int version;         // Version code to at least start with
  14. } check[] =
  15. {
  16.     0,       "PK\003",       0,     0,     ZIP, 4,    /* Pkzip */
  17.     0,       "`Ω",           0,     0,     ARJ, 8,    /* ARJ */
  18.     0,       "\x1A\x14\x00", 0,     0,     ARC7,52,   /* ARC 7.x */
  19.     0,       "HLSQZ1",       0,     0,     SQZ, 63,   /* SQZ 1.08 */
  20.     0,       "\x1aHP%",      0,     0,     HYP, 73,   /* Hyper 2.5 */
  21.     0,       "\x1aST%",      0,     0,     HYP, 73,   /* Hyper 2.5 */
  22.     0,       "HPAK",         0,     0,     HPK, 75,   /* Hpack 0.75c */
  23.     0,       "\x91" "3HF",   0,     0,     HAP, 76,   /* HAP 3.0 */
  24.     0,       "MDmd",         0,     0,     MD,  77,   /* MD 1.0 */
  25.     0,       "RE~^",         0,     0,     RAR, 78,   /* RAR 1.40 */
  26.     0,       "Rar!\x1a",     0,     0,     RAR, 81,   /* RAR 1.50 */
  27.     0,       "UC2",          0,     0,     UC2, 80,   /* UC2 */
  28.     0,       "GIF87",        0,     0,     GIF87, 83, /* GIF87a */
  29.     0,       "GIF89",        0,     0,     GIF89, 84, /* GIF89a */
  30.     2,       "-lh",          0,     0,     LZH, 2,    /* LHA 1.x/2.x */
  31.     2,       "-lz",          0,     0,     LZS, 1,    /* Larc 3.33 */
  32.     20,    "\xDC\xA7\xC4\xFD", 0, 0,     ZOO, 10,   /* Zoo */
  33.     1262,  "-lh",          1260,  1,     LZH, 19,   /* LHARC .COM 1.12 file */
  34.     1265,  "-lh",          1263,  1,     LZH, 14,   /* LHARC .COM 1.13 file */
  35.     1292,  "-lh",          1290,  1,     LZH, 12,   /* LHARC .COM 1.0 */
  36.     1294,  "-lh",          1292,  1,     LZH, 21,   /* LHARC .EXE 1.12S */
  37.     1297,  "-lh",          1295,  1,     LZH, 16,   /* LHARC .EXE 1.13S */
  38.     1324,  "-lh",          1322,  1,     LZH, 13,   /* LHARC .EXE 1.0 */
  39.     1637,  "-lh",          1635,  1,     LZH, 17,   /* LHARC .EXE 2.05 */
  40.     1638,  "-lh",          1636,  1,     LZH, 18,   /* LHARC .EXE 2.06 */
  41.     1872,  "-lh",          1870,  1,     LZH, 15,   /* LHARC .EXE 1.13L */
  42.     1873,  "-lh",          1871,  1,     LZH, 20,   /* LHARC .EXE 1.12L */
  43.     1947,  "-lh",          1945,  1,     LZH, 18,   /* LHARC .EXE 2.06 (with paths) */
  44.     2492,  "ZOO",          2535,  1,     ZOO, 59,   /* Sez (Zoo) 2.30 */
  45.     4694,  "NoGate",       6674,  1,     PAK, 25,   /* PAK   .EXE 1.5x */
  46.     4764,  "NoGate",       6744,  1,     PAK, 26,   /* PAK   .EXE 1.6x */
  47.     4887,  "NoGate",       6867,  1,     PAK, 28,   /* PAK   .EXE 2.5x */
  48.     5313,  "`Ω",           5313,  1,     ARJ, 55,   /* ARJ   .EXE 2.30B JR */
  49.     5329,  "`Ω",           5329,  1,     ARJ, 58,   /* ARJ   .EXE 2.30 JR */
  50.     5345,  "`Ω",           5345,  1,     ARJ, 39,   /* ARJ   .EXE 2.10 JR */
  51.     5377,  "`Ω",           5377,  1,     ARJ, 41,   /* ARJ   .EXE 2.20 JR */
  52.     5393,  "`Ω",           5393,  1,     ARJ, 56,   /* ARJ   .EXE 2.22 JR */
  53.     5473,  "`Ω",           5473,  1,     ARJ, 68,   /* ARJ   .EXE 2.39A JR */
  54.     5763,  "`Ω",           5763,  1,     ARJ, 70,   /* ARJ   .EXE 2.39F JR */
  55.     5779,  "`Ω",           5779,  1,     ARJ, 72,   /* ARJ   .EXE 2.41 JR */
  56.     5947,  "`Ω",           5947,  1,     ARJ, 33,   /* ARJ   .EXE 1.0 JR */
  57.     6159,  "`Ω",           6159,  1,     ARJ, 35,   /* ARJ   .EXE 1.10 JR */
  58.     6160,  "`Ω",           6160,  1,     ARJ, 37,   /* ARJ   .EXE 2.00 JR */
  59.     6491,  "RE~^",         6491,  1,     RAR, 79,   /* RAR   .EXE 1.40 SFX */
  60.     6679,  "NoGate",       8601,  1,     PAK, 27,   /* PAK   .EXE 2.0x - 2.1x */
  61.     6834,  "Buerg",        7746,  1,     ARC, 42,   /* ARC   .EXE 6.00 */
  62.     6836,  "Buerg",        7716,  1,     ARC, 43,   /* ARC   .EXE 6.02 */
  63.     8929,  "PKWARE",       9758,  1,     ARC, 29,   /* PKARC .EXE 3.5 */
  64.     9774,  "PKWARE",       13138, 1,     ARC, 31,   /* PKARC .EXE 3.61 */
  65.     9790,  "PKWARE",       13160, 1,     ARC, 30,   /* PKARC .EXE 3.6 */
  66.     12784, "PK\003",       12784, 1,     ZIP, 24,   /* PKZIP .EXE 1.10 */
  67.     13989, "`Ω",           13989, 1,     ARJ, 32,   /* ARJ   .EXE 1.00 */
  68.     14039, "`Ω",           14039, 1,     ARJ, 34,   /* ARJ   .EXE 1.10 */
  69.     14060, "`Ω",           14060, 1,     ARJ, 36,   /* ARJ   .EXE 2.00 */
  70.     14666, "`Ω",           14666, 1,     ARJ, 38,   /* ARJ   .EXE 2.10 */
  71.     14778, "`Ω",           14778, 1,     ARJ, 40,   /* ARJ   .EXE 2.20 */
  72.     14810, "`Ω",           14810, 1,     ARJ, 54,   /* ARJ   .EXE 2.30B */
  73.     14858, "`Ω",           14858, 1,     ARJ, 57,   /* ARJ   .EXE 2.30  */
  74.     15104, "`Ω",           15104, 1,     ARJ, 67,   /* ARJ   .EXE 2.39A */
  75.     15106, "`Ω",           15106, 1,     ARJ, 71,   /* ARJ   .EXE 2.41 */
  76.     15122, "`Ω",           15122, 1,     ARJ, 69,   /* ARJ   .EXE 2.39F */
  77.     15198, "PK\003",       15198, 1,     ZIP, 22,   /* PKZIP .EXE 0.92 */
  78.     15512, "PK\003",       15512, 1,     ZIP, 23,   /* PKZIP .EXE 1.02 */
  79.     15563, "PK\003",       15563, 1,     ZIP, 64,   /* PKZIP .EXE 2.00 */
  80.     15770, "PK\003",       15770, 1,     ZIP, 64,   /* PKZIP .EXE 2.04g */
  81. };
  82.  
  83. /*░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░*/
  84. void ARC_HANDLE::set_trailer_pos(AU *au)
  85. {
  86.     ARC_RECORD record;
  87.     long save_pos;
  88.     int  retCode;
  89.  
  90.     trailer_pos = -1;         /* No trailer by default */
  91.     save_pos = pos;
  92.  
  93.     while ((retCode = get_record(au, &record)) >= 0)
  94.     {
  95.         if (retCode == -2)
  96.             goto Error0;
  97.     }
  98.  
  99.     if (read_char() == 254)
  100.         trailer_pos = seek(0, SEEK_CUR);      // seek will need to be smarter
  101.  
  102. Error0:
  103.     pos = save_pos;
  104.     isFirst = TRUE;
  105.     rec_number = 0;
  106.     return;
  107. }
  108.  
  109. /*░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░*/
  110. static char pos_check(char *buffer, int num_chars, int pos, char *search)
  111. {
  112.     int len;
  113.  
  114.     len = strlen(search);
  115.     if (num_chars < pos+len)
  116.         return FALSE;
  117.  
  118.     if (memcmp(search, buffer+pos, len) == 0)
  119.         return TRUE;
  120.     else
  121.         return FALSE;
  122. }
  123. /*░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░*/
  124. static BOOLEAN ValidArjHeader(char *buffer, unsigned int pos)
  125. {
  126.     unsigned int size;
  127.     unsigned long crc1, crc2;
  128.     unsigned int j;
  129.     unsigned char c1,c2,c3,c4;
  130.  
  131.  
  132.     size = (buffer[pos+3] << 8) + buffer[pos+2];
  133.     if (size <= 2600)
  134.     {
  135.         crc1 = crc32_string(buffer+pos+4, size);
  136.         j = pos+4+size;
  137.  
  138.         c1 = buffer[j];
  139.         c2 = buffer[j+1];
  140.         c3 = buffer[j+2];
  141.         c4 = buffer[j+3];
  142.  
  143.         crc2 = (unsigned long)c1 |
  144.               ((unsigned long)c2 << 8) |
  145.               ((unsigned long)c3 << 16) |
  146.               ((unsigned long)c4 << 24);
  147.  
  148.         if (crc1 == crc2)
  149.         {
  150.             return TRUE;
  151.         }
  152.     }
  153.     return FALSE;
  154. }
  155. /*░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░*/
  156. BOOLEAN ARC_HANDLE::search_arj(char *file_name, int num_chars, long start,
  157.                                long end, char *buffer)
  158. {
  159.     unsigned int c;
  160.     unsigned int i;
  161.  
  162.     if (num_chars > start)
  163.     {
  164.         c = end;
  165.         if (c > num_chars)
  166.             c = num_chars;
  167.         c--;
  168.         for (i = start; i < c; i++)
  169.         {
  170.             if (buffer[i] == '\x60' && buffer[i+1] == '\xEA')
  171.             {
  172.                 if (ValidArjHeader(buffer, i))
  173.                 {
  174.                     pos = i;
  175.                     isFirst = FALSE;
  176.                     type = ARJ;
  177.                     if (strstr(file_name, ".EXE") != NULL ||
  178.                         strstr(file_name, ".COM") != NULL)
  179.                     {
  180.                         is_self = TRUE;
  181.                     }
  182.                     else
  183.                         is_self = FALSE;
  184.  
  185.                     return TRUE;
  186.                 }
  187.             }
  188.         }
  189.     }
  190.     return FALSE;
  191. }
  192. /*░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░*/
  193. /* .HA files are hard to identify.    This function takes a stab at reducing */
  194. /* the possibility of falsely identifying a file */
  195.  
  196. BOOLEAN ARC_HANDLE::search_ha(int num_chars, char *buffer)
  197. {
  198.     unsigned int i;
  199.     unsigned int num_to_check;
  200.  
  201.     /* .HA files start with HA.  Easy enough to check for */
  202.  
  203.     if (buffer[0] != 'H' || buffer[1] != 'A')
  204.         return FALSE;
  205.  
  206.     /* HA files are at least 34 bytes long */
  207.  
  208.     if (num_chars < 34)
  209.         return FALSE;
  210.  
  211.     /* HA files almost certainly have some data that can be recoginized
  212.        as binary inside them */
  213.  
  214.     num_to_check = num_chars > 200 ? num_chars : 200;
  215.     for (i=2; i < num_to_check; i++)
  216.     {
  217.         if (!is_binary_file_char(buffer[i]))
  218.         {
  219.             pos = i;
  220.             is_self = FALSE;
  221.             isFirst = TRUE;
  222.             type = HA;
  223.             version = 74;
  224.             return TRUE;
  225.         }
  226.     }
  227.     return FALSE;
  228. }
  229. /*░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░*/
  230. long ARC_HANDLE::find_last_non_zero()
  231. {
  232.     char buffer[129];
  233.     int  buf_size;
  234.     int  i;
  235.  
  236.     seek(-128L, SEEK_END);         /* 128 from the end */
  237.     buf_size = read(buffer, 128);
  238.     for (i = buf_size-1; i >= 0; i--)
  239.     {
  240.         if (buffer[i] != '\0')
  241.             break;
  242.     }
  243.     return file_length() - buf_size + i;
  244. }
  245. /*░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░*/
  246. STATUS ARC_HANDLE::get_format(AU *au, char *file_name)
  247. {
  248.     int      c,d,e;
  249.     int      num_chars;
  250.     int      i;
  251.     char    *buffer;
  252.     long     find_pos;
  253.  
  254.     buffer = (char *)au_malloc(au, LAST_BYTE);
  255.     seek(0, SEEK_SET);
  256.     num_chars = read_raw(buffer, LAST_BYTE);
  257.  
  258.     is_self = FALSE;
  259.     version = 0;                /* Unknown version */
  260.     pos = 0;
  261.  
  262.     for (i=0; i<sizeof(check)/sizeof(struct CHECK); i++)
  263.     {
  264.         if (pos_check(buffer, num_chars, check[i].search_pos, check[i].match))
  265.         {
  266.             if (check[i].is_self)
  267.             {
  268.                 if (!au->self_extracts)
  269.                     break;
  270.                 if (strstr(file_name, ".COM") == NULL &&
  271.                     strstr(file_name, ".EXE") == NULL)
  272.                 {
  273.                     break;
  274.                 }
  275.             }
  276.             /* Additional check on arj to make sure it isn't a false
  277.                recognition */
  278.  
  279.             if (check[i].type == ARJ)
  280.             {
  281.                 if (!ValidArjHeader(buffer, (long)check[i].start_pos))
  282.                     break;
  283.             }
  284.  
  285.             pos = (long)check[i].start_pos;
  286.             version = check[i].version;
  287.             is_self = check[i].is_self;
  288.             type = check[i].type;
  289.             goto Error0;
  290.         }
  291.     }
  292.  
  293. /* Arj is pretty flakey about changing every darn version.    their lite
  294.    self extractors seem to work in the 5000 to 6500 range, the regular
  295.    from 13500 to 18000 */
  296.  
  297.     if (search_arj(file_name, num_chars, 0, 4999, buffer))
  298.     {
  299.         version = 8;
  300.         goto Error0;
  301.     }
  302.  
  303.     if (search_arj(file_name, num_chars, 5000, 6500, buffer))
  304.     {
  305.         version = 65;
  306.         goto Error0;
  307.     }
  308.  
  309.     if (search_arj(file_name, num_chars, 6501, 13499, buffer))
  310.     {
  311.         version = 1;
  312.         goto Error0;
  313.     }
  314.  
  315.     if (search_arj(file_name, num_chars, 13500, 18000, buffer))
  316.     {
  317.         version = 66;
  318.         goto Error0;
  319.     }
  320.  
  321. /* Try for HA */
  322.  
  323.     if (search_ha(num_chars, buffer))
  324.     {
  325.         goto Error0;
  326.     }
  327.  
  328. /* Try for ARC/PAK *************************/
  329.  
  330.     seek(0, SEEK_SET);
  331.     c = read_char();
  332.     d = read_char();
  333.  
  334.     if (c == 26 && d > 0 && d < 12)
  335.     {
  336.         find_pos = find_last_non_zero();
  337.         seek(find_pos, SEEK_SET);
  338.         c = read_char();
  339.         if (c == 26)
  340.         {
  341.             version = 47;
  342.             type = ARC;
  343.         }
  344.         else
  345.         {
  346.             version = 48;
  347.             type = PAK;
  348.         }
  349.         goto Error0;
  350.     }
  351.  
  352. /* Try for LBR */
  353.  
  354.     if (c == 0x00 && d == 0x20)
  355.     {
  356.         if (read_char() == 0x20)
  357.         {
  358.             seek(10, SEEK_SET);
  359.             c = read_char();
  360.             d = read_char();
  361.             e = read_char();
  362.             if (c==0x20 && d==0x20 && e==0x00)
  363.             {
  364.                 version = 61;
  365.                 type = LBR;
  366.                 goto Error0;
  367.             }
  368.         }
  369.     }
  370.  
  371. /* Try for DWC */
  372.  
  373.     find_pos = find_last_non_zero();
  374.     seek(find_pos-2, SEEK_SET);
  375.  
  376.     c = read_char();
  377.     d = read_char();
  378.     e = read_char();
  379.  
  380.     if (c=='D' && d=='W' && e=='C')
  381.     {
  382.         version = 11;
  383.         type = DWC;
  384.         goto Error0;
  385.     }
  386.  
  387.     type = NONARC;                 /* Not an archive */
  388.  
  389. Error0:
  390.     free(buffer);
  391.  
  392.     /* Set the trailer information pointer if .PAK */
  393.     if (type == PAK && au->unarc_paths == ON)
  394.     {
  395.         set_trailer_pos(au);
  396.         type = PAK;
  397.     }
  398.     else if (type == ARC)
  399.     {
  400.         set_trailer_pos(au);
  401.         if (trailer_pos == -1)
  402.             type = ARC;
  403.         else
  404.         {
  405.             if (au->unarc_paths != ON)
  406.                 trailer_pos = -1;
  407.             version = 48;
  408.             type = PAK;
  409.         }
  410.     }
  411.  
  412.     return SUCCESS;
  413. }
  414.  
  415.  
  416.